import { boot } from 'quasar/wrappers'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import { LoadingBar } from 'quasar'
/* eslint-disable */
let mock = axios

mock.defaults.xsrfCookieName = 'csrftoken'
mock.defaults.xsrfHeaderName = "X-CSRFTOKEN"

if (process.env.DEBUGGING && false) {
  mock = new MockAdapter(axios)
  // 我们先这样写 之后再重构

  const headTmp = [
    'http://tp.azqqw.com/d/tp/tx/202111071400/16361656222816556.jpg',
    'https://cdn.quasar.dev/img/avatar2.jpg'
  ]

  const userDb = [
    {
      id: '1',
      sid: '1813004316',
      psw: '123',
      name: '王彦伟',
      head: headTmp[0],
      type: 'student',
      extraInfo: [] // 使用kv设计模式
    },
    {
      id: '2',
      sid: '2013040206',
      psw: '456',
      name: '党男男',
      head: headTmp[1],
      type: 'student',
      extraInfo: [] // 使用kv设计模式
    },
    {
      id: '3',
      tid: 't1', // 老师也有编号，这里后续需要调整
      psw: '111',
      name: '李众',
      head: headTmp[1],
      type: 'teacher',
      extraInfo: [] // 使用kv设计模式
    },
    {
      id: '4',
      tid: 't2', // 老师也有编号，这里后续需要调整
      psw: '111',
      name: '张三',
      head: headTmp[1],
      type: 'teacher',
      extraInfo: [] // 使用kv设计模式
    }
  ]

  const compCateDb = [
    {
      id: '1',
      name: '第十二届蓝桥杯全国软件和信息技术专业人才大赛个人赛省赛',
      shortName: '2020年蓝桥杯',
      date: Date.now(), // 录入系统时间 后续我们可根据此优化选择列表
      level: ['一等奖', '二等奖', '三等奖'], // 这里可以使用变量覆盖，所以不担心会重复
      isGroup: false,
      needTitle: false
    },
    {
      id: '2',
      name: '2021第七届中国国际“互联网+”大学生创新创业大赛',
      shortName: '2021年互联网+',
      level: ['金奖', '银奖', '铜奖'],
      date: Date.now(),
      isGroup: true,
      needTitle: true
    }
  ]

  const compDb = [
    // 正常展示 - 单项
    {
      id: '1',
      comp: {
        ...compCateDb[1 - 1],
        id: '1',
        level: '一等奖'
      },
      pics: ['banner_top_7th_1_n.jpg'], // 这里要指向minio
      owner: [
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责务实'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: ['3'],
          owner: ['1'],
          allAccepted: true, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: '2021/8/24' // 如有评价时间应该以此为主
      }
    },
    // 正常展示 - 多项
    {
      id: '2',
      comp: {
        ...compCateDb[2 - 1],
        id: '2',
        level: '金奖',
        title: '机遇'
      },
      pics: ['banner_top_7th_1_n.jpg'],
      owner: [
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责务实'
        },
        {
          ...userDb[2 - 1],
          id: '2',
          job: '负责爱我'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: ['3'],
          owner: ['1', '2'],
          allAccepted: true, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    },
    // 待审批 - 我
    {
      id: '3',
      comp: {
        ...compCateDb[2 - 1],
        id: '2',
        level: '金奖',
      },
      pics: ['banner_top_7th_1_n.jpg'],
      owner: [
        {
          ...userDb[2 - 1],
          id: '2',
          job: '负责务实'
        },
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责爱我'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: [],
          owner: [],
          allAccepted: false, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    },
    // 待审批 - 他人
    {
      id: '4',
      comp: {
        ...compCateDb[2 - 1],
        id: '2',
        level: '金奖',
      },
      pics: ['banner_top_7th_1_n.jpg'],
      owner: [
        {
          ...userDb[2 - 1],
          id: '2',
          job: '负责务实'
        },
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责爱我'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: [],
          owner: ['1'],
          allAccepted: false, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    },
    // 待审批 - 教师
    {
      id: '5',
      comp: {
        ...compCateDb[2 - 1],
        id: '2',
        level: '金奖',
      },
      pics: ['banner_top_7th_1_n.jpg'],
      owner: [
        {
          ...userDb[2 - 1],
          id: '2',
          job: '负责务实'
        },
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责爱我'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: [],
          owner: ['1', '2'],
          allAccepted: false, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    },
    // 被拒绝
    {
      id: '6',
      comp: {
        ...compCateDb[2 - 1],
        id: '2',
        level: '金奖',
        title: 'test'
      },
      pics: ['banner_top_7th_1_n.jpg'],
      owner: [
        {
          ...userDb[2 - 1],
          id: '2',
          job: '负责务实'
        },
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责爱我'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: [],
          owner: ['1', '2'],
          allAccepted: false, // 用于服务端检查加速
        },
        rejected: {
          id: '3',
          msg: '太拉了'
        },
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    },
    // 只差我同意
    {
      id: '7',
      comp: {
        ...compCateDb[2 - 1],
        id: '2',
        level: '金奖',
        title: '请消失并出现在主页上'
      },
      pics: ['banner_top_7th_1_n.jpg'],
      owner: [
        {
          ...userDb[2 - 1],
          id: '2',
          job: '负责务实'
        },
        {
          ...userDb[1 - 1],
          id: '1',
          job: '负责爱我'
        }
      ],
      teacher: [
        {
          ...userDb[3 - 1],
          id: '3',
        }
      ],
      date: {
        certDate: Date.now(),
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: [],
          owner: ['1', '2'],
          allAccepted: false, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    }
  ]

  const loginDb = {}

  mock.onPost("api/login").reply(function (config) {
    const user = JSON.parse(config.data)
    // 得到数据的API应该记录拿到的样子是什么
    /*
    {
      id: '', // 这里指的是sid（对于学生），或者tid（指教师）
      password: ''
    }
    */
    let selectedUser = null;
    userDb.forEach(u => {
      if (u.sid === user.id || u.tid === user.id) selectedUser = u
    })
    if (!selectedUser || selectedUser.psw !== user.password) selectedUser = null
    if (!!selectedUser) {
      // 生成token并且将其放到数据库中 这样我们就知道是谁了
      const token = Math.floor((Math.random() * 100) + 1)
      loginDb[token] = selectedUser
      return [200, {
        user: {
          ...selectedUser,
          psw: '', // 清除掉密码这种敏感信息
          token: token // 登陆鉴权使用
        }
      }]
    } else {
      return [400, {
        msg: '用户名不存在或者用户名于密码不匹配'
      }]
    }
  });

  // 这里要添加对参数的支持 或者我们将其抽取成数据库
  mock.onGet('/api/getInfo/').reply(function (config) {
    const infoId = config.params.id
    const curUser = getCurrentUser(config)
    // 我们可以顺便检查其是否可以展示,主要看其是否全部审批通过了
    const info = compDb[infoId - 1]
    // 这里需要控制必须当前用户才能访问
    if (info.status.accepted.allAccepted || info.owner.concat(info.teacher).map(o => o.id).indexOf(curUser.id) !== -1) {
      return [200, {
        info: info
      }]
    } else {
      return [400, {
        msg: '项目不存在或者未审批结束'
      }]
    }
  })

  // 获取主页数据
  mock.onGet('/api/getList').reply(function (config) {
    // 我们要从里面得到所有符合要求的进行返回 只返回审批了的
    return [200, {
      infoList: compDb.filter(c => c.status.accepted.allAccepted === true)
    }]
  })

  function getCurrentUser (config) {
    console.log('user in', config.headers.Authorization)
    return loginDb[config.headers.Authorization]
  }

  // 获取所有与我有关的 并且完全审批的数据
  mock.onGet('/api/getMyList').reply(function (config) {
    const curUser = getCurrentUser(config)
    if (!curUser) {
      return [400, {
        msg: '未登录'
      }]
    }
    return [200, {
      infoList: compDb.filter(c => c.status.accepted.allAccepted && c.owner.concat(c.teacher).map(o => o.id).indexOf(curUser.id) !== -1) // 这里需要得到用户的id
    }]
  })

  mock.onGet('/api/getCateList').reply(200, {
    cateList: compCateDb
  })

  mock.onPost("api/getStuShortInfo").reply(function (config) {
    const stu = JSON.parse(config.data)
    const sid = stu.sid
    // 通过sid查询学生
    const pos = userDb.map(u => u.sid).indexOf(sid)
    if (sid != null && pos === -1) {
      return [400, {
        msg: '无此同学'
      }]
    } else {
      return [200, {
        student: {
          ...userDb[pos],
          psw: '' // 注意去掉敏感信息
        }
      }]
    }
  })

  mock.onPost("api/getTeaShortInfo").reply(function (config) {
    // 这里与获取学生信息产生严重重复 需要合并优化
    const tea = JSON.parse(config.data)
    const name = tea.name
    // 通过name查询教师
    const pos = userDb.map(u => u.name).indexOf(name)
    if (name != null && pos === -1) {
      return [400, {
        msg: '无此教师'
      }]
    } else {
      return [200, {
        teacher: {
          ...userDb[pos],
          psw: '' // 注意去掉敏感信息
        }
      }]
    }
  })

  mock.onPost('api/submitCompRequest').reply(function(config) {
    let comp = JSON.parse(config.data)
    // 我们要检查很多东西：用户是否登陆、内容是否与表单内容一致、提交的表单是否符合要求、违规字段屏蔽
    // 我们需要为comp分配id
    console.log('serverside', comp)
    comp = {
      id: compDb.length + 1,
      comp: {
        ...compCateDb[comp.comp.id - 1],
        level: comp.comp.level,
        title: comp.comp.title
      },
      pics: comp.pics,
      owner: comp.owner.map(o => {
        return {
          ...userDb[o.id - 1],
          job: o.job
        }
      }),
      teacher: comp.teacher.map(t => {
        return {
          ...userDb[t - 1],
        }
      }),
      date: {
        certDate: comp.date.certDate,
        uploadDate: Date.now()
      },
      status: {
        accepted: {
          // 我们主要检查这里来判断情况
          teacher: [],
          owner: [],
          allAccepted: false, // 用于服务端检查加速
        },
        rejected: null,
        lastChangeDate: Date.now() // 如有评价时间应该以此为主
      }
    }
    compDb.push(comp)
    return [
      200, {
        info: comp
      }
    ]
  })

  mock.onGet('api/getRelatedComps').reply(function(config) {
    const curUser = getCurrentUser(config)
    console.log('?', curUser)
    // 我们要按照界面返回数据
    // 我们考虑的是每次更新同步更新数据结构 别老是刷新
    return [
      200, {
        // 我们不用区分，这些是前端的事情
        // 返回没有被批准、owner里面有当前用户的数据
        compList: compDb.filter(c => !c.status.accepted.allAccepted && c.owner.concat(c.teacher).map(s => s.id).indexOf(curUser.id) !== -1)
      }
    ]
  })

  mock.onPost('api/handleRequest').reply(function(config) {
    const curUser = getCurrentUser(config)
    const handle = JSON.parse(config.data)
    /*
    {
      cerId,
      action: 'accept' | 'reject'
    }
    */
    // 在批准的时候要注意被批准的证书里面是否有这个用户、时间是否有效（是否超时）、是否已经被拒绝（不接受批准）
    const comp = compDb[handle.id - 1]
    console.log(comp, handle)
    if (handle.action === 'accept') {
      if (curUser.type === 'student') {
        comp.status.accepted.owner.push(curUser.id)
      } else if (curUser.type === 'teacher') { // 为什么我们需要为教师单独开一个文档呢？
        comp.status.accepted.teacher.push(curUser.id)
      }
      // 检查是否都同意了 -- 这里用不安全的办法
      comp.status.accepted.allAccepted = comp.status.accepted.owner.length === comp.owner.length && comp.status.accepted.teacher.length === comp.teacher.length
      // 这里最好以时间戳的方式提供 可以保证不同地区的最大兼容
      comp.status.lastChangeDate = Date.now()
    } else if (handle.action === 'reject') {
      comp.status.rejected = {
        id: curUser.id,
        msg: 'unimplemented'
      }
    }
    return [200, {
      info: comp // 将结果返回 前端放到其应该在的位置上
    }]
  })

}

// Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here;
// If any client changes this (global) instance, it might be a
// good idea to move this instance creation inside of the
// "export default () => {}" function below (which runs individually
// for each client)
const api = axios.create({ 
  baseURL: 'http://localhost/api',
  withCredentials: true,
  xsrfHeaderName: 'X-CSRFToken',
  xsrfCookieName: 'csrftoken',
})

axios.interceptors.request.use(function (config) {
  LoadingBar.start()
  return config;
}, function (error) {
  LoadingBar.stop()
  return Promise.reject(error);
});

// Add a response interceptor
axios.interceptors.response.use(function (response) {
  LoadingBar.stop()
  return response;
}, function (error) {
  LoadingBar.stop()
  if (!error.response) {
    error.response = {
      data: {
        detail: '致命错误，请联系管理员！'
      }
    }
  }
  return Promise.reject(error);
});


export default boot(({ app }) => {
  // for use inside Vue files (Options API) through this.$axios and this.$api

  app.config.globalProperties.$axios = mock
  // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
  //       so you won't necessarily have to import axios in each vue file

  app.config.globalProperties.$axxios = axios
  // for testing file upload

  app.config.globalProperties.$api = api
  // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
  //       so you can easily perform requests against your app's API
})

export { api }
